<template>
  <div class="editor-container" id="editor-container">
    <div class="editor-header">
      <div>
        <el-tooltip slot="reference" content="设备视图" placement="top" :open-delay="300" v-if="component.type!=='compositeWidget'">
	        <span class=" font-size-14 cursor-pointer icon-hover" @click="showDeviceDialog = true">设备视图</span>
        </el-tooltip>
        <el-tooltip slot="reference" content="命令视图" placement="top" :open-delay="300" v-if="component.type==='compositeWidget'">
          <span class=" font-size-14 cursor-pointer icon-hover" @click="showCommandDialog = true">命令视图</span>
        </el-tooltip>
        <el-tooltip slot="reference" content="全局变量" placement="top" :open-delay="300">
	        <span class=" font-size-14 cursor-pointer icon-hover mar-lft-10" @click="showGlobalVarDialog = true">全局变量</span>
        </el-tooltip>
        <el-tooltip slot="reference" content="真值反馈" placement="top" :open-delay="300">
	        <span class=" font-size-14 cursor-pointer icon-hover mar-lft-10" @click="showIftttDialog = true">真值反馈</span>
        </el-tooltip>
	      <el-tooltip slot="reference" content="主题色" placement="top" :open-delay="300">
		      <span class=" font-size-14 cursor-pointer icon-hover mar-lft-10" @click="showThemeDialog = true">主题色</span>
	      </el-tooltip>
	      <el-popover
		      v-model="showScalePopper"
		      width="400" trigger="click"
		      placement="bottom-start"
		      popper-class="custom-popover">
		      <el-tooltip slot="reference" :visible-arrow="false" content="比例缩放" placement="top" :open-delay="300">
			      <span class=" font-size-14 cursor-pointer icon-hover mar-lft-10">全局比例缩放</span>
		      </el-tooltip>
		      <WidgetScaleControl
			      v-if="showScalePopper"
			      :is-global="true"
			      @scaled="showScalePopper = false"></WidgetScaleControl>
	      </el-popover>
      </div>

      <div>
        <span class="mar-lft-10">{{component.name || '--'}}</span>
        <el-tooltip slot="reference" content="撤销" placement="top" :open-delay="300">
          <i class="el-icon-refresh-left font-size-22 mar-lft-10 cursor-pointer icon-hover"
             @click="undoRedoHandler('undo')"></i>
        </el-tooltip>
        <el-tooltip slot="reference" content="重做" placement="top" :open-delay="300">
          <i class="el-icon-refresh-right font-size-22 mar-lft-10 cursor-pointer icon-hover"
             @click="undoRedoHandler('redo')"></i>
        </el-tooltip>
      </div>

      <div class="flex-justify-start">
	      <div>
		      <span class="font-size-14 mar-rgt-5">冻结模式</span>
		      <el-switch v-model="freezeMode" @change="freezeModeChange"></el-switch>
	      </div>
        <el-tooltip slot="reference" content="保存" placement="top" :open-delay="300">
          <i v-if="userInfo.role !== userRoleCfg.guest"
             class="iconfont icon-save font-size-24 mar-lft-10 cursor-pointer icon-hover"
             @click="saveComponent"></i>
        </el-tooltip>
        <el-tooltip slot="reference" content="刷新" placement="top" :open-delay="300">
          <i class="iconfont icon-exchangerate font-size-24 mar-lft-10 cursor-pointer icon-hover"
             @click="refresh"></i>
        </el-tooltip>
        <div class="display-inline-block">
          <el-tooltip slot="reference" content="截图" placement="top" :open-delay="300">
            <i class="iconfont  icon-shuffling-banner font-size-24 mar-lft-10 cursor-pointer icon-hover"
               @click="transDomToImage"></i>
          </el-tooltip>
          <el-tooltip slot="reference" content="预览" placement="top" :open-delay="300">
            <i class="iconfont icon-start font-size-22 mar-lft-10 cursor-pointer icon-hover" @click="preview"></i>
          </el-tooltip>
        </div>
      </div>
    </div>
    <div class="display-flex width-100">
      <div class="editor-aside">
        <AsideCollapse
	        :title="component.name || '--'"
	        :hide-operation="false"
	        @addPage="addPage"
	        @sort="sorting => pageTreeSorting = sorting">
          <AsideWidgetTree
	          editor-type="component"
	          :page-hdl="pageHdl"
	          :is-sorting="pageTreeSorting"></AsideWidgetTree>
        </AsideCollapse>
        <div class="component-widget-picker-tab">
          <div v-for="(item, index) in widgetTabs" :key="index" @click="changeTab(item.type, index)"
               :class="{'widget-picker-active-tab': activePickerTab === index}">
            <el-tooltip :content="item.text" placement="top" :open-delay="300">
              <span>{{item.name}}</span>
            </el-tooltip>
          </div>
        </div>
        <div>
          <div v-show="widgetType === 'atom'">
            <AsideWidgetPicker widget-type="atom"></AsideWidgetPicker>
          </div>
          <div v-show="widgetType === 'function'">
            <AsideWidgetPicker widget-type="function"></AsideWidgetPicker>
          </div>
          <div v-show="widgetType === 'composite'">
            <AsideComponentPicker widget-type="composite"></AsideComponentPicker>
          </div>
          <div v-show="widgetType === 'device'">
            <AsideComponentPicker widget-type="device"></AsideComponentPicker>
          </div>
        </div>
      </div>
      <div v-loading="loading" class="flex-1 color-white">
        <EditorWorkspace
	        ref="workspace"
	        editor-type="component"
	        @save="saveComponent"
	        @jumpLogic="jumpLogic"></EditorWorkspace>
      </div>
    </div>
    <div>
      <!--设备视图-->
	    <GlobalDevices v-model="showDeviceDialog" editor-type="component" :component-id="component._id" ></GlobalDevices>
      <!--命令视图-->
      <GlobalCommand v-model="showCommandDialog" :command-data="commandData" ></GlobalCommand>
      <!-- 全局变量配置 -->
	    <GlobalVariables v-model="showGlobalVarDialog" :variables="component.globalVar" @submit="globalVarSubmit"></GlobalVariables>
	    <!-- 真值反馈配置 -->
	    <IftttLogic v-model="showIftttDialog" editor-type="component" :component-id="component._id" :activeLogic="activeLogic"></IftttLogic>
	    <!-- 主题色配置 -->
	    <el-dialog title="主题色配置" :visible.sync="showThemeDialog" :close-on-click-modal="false" width="680px">
		    <ThemePicker v-model="component.theme" @change="themeChange"></ThemePicker>
	    </el-dialog>
    </div>
	  <WidgetPicker editor-type="component"></WidgetPicker>
    <TokenRefresh :isEditor="true"></TokenRefresh>
  </div>
</template>

<script>
  import {PageHandler} from "@/modules/IDE/pageHandler";
  import EmptyContent from "@/components/IDE/EmptyContent.vue";
  import CustomColorPicker from '@/components/IDE/colorPicker/Color.vue';
  import AsideCollapse from '../editor/aside/AsideCollapse.vue';
  import AsideWidgetPicker from '../editor/aside/AsideWidgetPicker.vue';
  import AsideWidgetTree from '../editor/aside/AsideWidgetTree.vue';
  import WidgetPicker from "@/components/IDE/widgetPicker/WidgetPicker.vue";
  import EditorWorkspace from '../editor/EditorWorkspace.vue';
  import GlobalVariables from '../editor/global/GlobalVariables.vue';
  import {base64toFile, editorConfigPreview, formatHttpParams, getUserInfo, messageHandle,generateUID} from '@/utils';
  import {mapActions, mapState} from 'vuex';
  import {userRoleCfg} from "@/config/ide/common";
  import {Dom2ImageHandler} from "@/modules/domToImageHandler";
  import GlobalDevices from "@/page/IDE/editor/global/GlobalDevices.vue";
  import IftttLogic from '../editor/global/IftttLogic.vue';
  import API from "@/api";
  import {WidgetFactory} from "@/modules/IDE/widgetFactory";
  import TokenRefresh from '@/components/TokenRefresh';
  import {themeOption, uploadFileType} from "@/config/common";
  import {msgCode} from "@/config/string";
  import ThemePicker from "@/components/IDE/ThemePicker.vue";
  import WidgetScaleControl from "@/components/IDE/WidgetScaleControl.vue";
  import GlobalCommand from "@/page/IDE/editor/global/GlobalCommand.vue";
  import AsideComponentPicker from "@/page/IDE/editor/aside/AsideComponentPicker.vue";
  export default {
    name: 'ComponentEditor',
    components: {
      AsideComponentPicker,
	    WidgetPicker,
	    WidgetScaleControl,
	    ThemePicker,
	    GlobalDevices,
      EmptyContent, CustomColorPicker, AsideCollapse,
      AsideWidgetPicker, AsideWidgetTree,GlobalCommand,
      EditorWorkspace, GlobalVariables, IftttLogic, TokenRefresh
    },
    data() {
      return {
        loading: false,
        userRoleCfg: userRoleCfg,
        userInfo: getUserInfo(),
        component: {},
        pageHdl: new PageHandler('component'),
	      pageTreeSorting: false,
	      freezeMode: false, // 是否开始冻结模式
        imgLength: 0,
        widgetTabs: [
          {name: '原子组件', type: 'atom',text:'它是UI设计中最基础、不可再拆分的最小单元'},
          {name: '功能组件', type: 'function',text:'由系统内置代码生成的预设模块，其样式固定不可更改，但支持通过参数动态配置核心功能或行为'},
          // {name: '复合', type: 'composite'},
          // {name: '设备', type: 'device'},
        ],
        widgetType: 'atom',
        activePickerTab: 0,
        showDeviceDialog: false,
	      showThemeDialog: false,
	      showScalePopper: false,
        componentDeviceList: [], // 组件已添加的设备
        showGlobalVarDialog: false,
	      showIftttDialog: false,
        activeLogic:'room',
        showCommandDialog: false,
        commandData:{},
        componentScenes:[
          {
            key: 'SystemOn',
            sceneId: 'SystemOn',
            name: '开启系统'
          },
          {
            key: 'SystemOff',
            sceneId: 'SystemOff',
            name: '关闭系统'
          },
        ]
      };
    },
    computed: {
      ...mapState({
	      globalDeviceList: state => state.ide.globalDeviceList,
        selectWidgetIds: state => state.ide.selectWidgetIds,
      }),
      commandType() {
        if(this.component.type === 'compositeWidget' && this.component.generalProtocolId)  {
          return {
            type: 'generalProtocol',
            protocolId: this.component.generalProtocolId,
          };
        }else if(this.component.type === 'compositeWidget' && this.component.widgetType==='device' && this.component.protocolId){
          return {
            type: 'deviceProtocol',
            protocolId: this.component.protocolId,
          };
        }
      }
    },
    created() {
      this.component = {_id: this.$route.params.cid};
      this.getComponentDetail();
      this.getComponentAvailableAssetList();

    },
    mounted() {
      this.$EventBus.$on('tokenExpired', (expire = false) => {
        expire && this.$router.push({path: '/login'});
      });
    },
    beforeDestroy() {
      this.$EventBus.$off('tokenExpired');
    },
    destroyed() {
    },
    methods: {
      ...mapActions([
        'updateImageAssetsList',
        'updateActiveTheme',
        'updateFreezeMode',
        'updateGlobalVarList',
        'updateGlobalDeviceList',
        'updateGlobalLogicList',
        'updateCurPageHandler',
        'updateGlobalCommandList',
        'updateGlobalDeviceList',
        'updateGlobalScenesList'
      ]),
      refresh() {
        WidgetFactory.clear();
        this.getComponentDetail();
        this.getComponentAvailableAssetList();
      },
      getComponentDetail() {
        this.loading = true;
        API.component.componentDetail({componentId: this.component._id}).then(resp => {
          this.loading = false;
          this.component = resp.data;
          const {
            _id, category, name, widgets = [],
            globalVar = [], theme = 'theme1', type,
            widgetSize = {}
          } = this.component;
          this.updateGlobalVarList(globalVar);
          this.updateGlobalScenesList(this.componentScenes);
          const colorsTheme = themeOption.find(item => item[theme]);
          colorsTheme && this.updateActiveTheme(colorsTheme[theme]);
          this.pageHdl.initPages(widgets, {componentId: _id, name, category, type, widgetSize});
          this.pageHdl.refreshPageWidgetSortNo();
          if (widgets.length === 0 && type === 'compositeWidget') {
            this.addDetailPage(this.pageHdl.pages[0].id, `${this.pageHdl.pages[0].name}的详情页`);
          }
          this.updateCurPageHandler(this.pageHdl);
          // 初始化后默认选中第一个页面
          this.pageHdl.updateActivePage(this.pageHdl.pages[0]);
          this.$EventBus.$emit('selectWidget', this.pageHdl.activePage);
          if (this.component.type === 'compositeWidget') {
            this.getGlobalCommandList()
          }
        }).catch(err => {
          this.loading = false;
        });
      },
      getComponentAvailableAssetList() {
        API.component.componentAvailableAssetList().then(resp => {
          this.updateImageAssetsList(resp.data || []);
        });
      },
      globalVarSubmit(variables = []) {
        this.showGlobalVarDialog = false;
        this.component.globalVar = variables;
        this.updateGlobalVarList(variables);
      },
      addPage() {
        const newPage = this.pageHdl.createRootPage({isAppendage: true, name: `${this.pageHdl.pages[0].name}全局弹框`,appendDialogId:this.pageHdl.pages[0].id});
        this.$EventBus.$emit('selectWidget', this.pageHdl.activePage);
        const widgets = WidgetFactory.getWidgetFlattenChildren(newPage);
        WidgetFactory.undoRedoHdl.operationHdl([{operationType: 'add', widgets: widgets}]);
      },
      addDetailPage(id, name) {
        this.pageHdl.createRootPage({isAppendage: true, name: name, appendageId: id,});
      },
      undoRedoHandler(operation) {
        const workspace = this.$refs['workspace'];
        workspace && workspace.undoRedoHandler(operation);
      },
      saveComponent() {
        this.loading = true;
        const {
          _id = '', name = '', category = '', version = '', theme = 'theme1',
          globalVar = [], previewImages = [], description = '', group = '',
          isWidget, widgetType, deviceType = '', protocolId = '', widgetSize = {},
          remarks = '',generalProtocolId = ''
        } = this.component;
        if (!_id) return;
        const params = {
          _id: _id,
          name: name,
          category: category,
          version: version,
          previewImages: previewImages,
          description: description,
          devices: this.globalDeviceList,
          widgets: PageHandler.getPageFlattenWidgets(this.pageHdl.pages),
          theme: theme,
          globalVar: globalVar,
          remarks: remarks,
          group: group,
          isWidget: isWidget,
          widgetType: widgetType,
          deviceType: deviceType,
          protocolId: protocolId,
          widgetSize: widgetSize,
          generalProtocolId: generalProtocolId,
          status: 0
        };
        console.log('##### params #####', params);
        API.component.componentEdit(formatHttpParams(params)).then(resp => {
          this.loading = false;
          this.$message({message: '组件配置保存成功!', type: 'success', duration: 1500});
          WidgetFactory.refreshWidgetsEntityId(resp.data);
          WidgetFactory.resetWidgetsHash(params.widgets);
          WidgetFactory.resetWidgetDefaultUI();
        }).catch(err => {
          this.loading = false;
        });
      },
      preview() {
        editorConfigPreview({type: 'component', componentId: this.component._id});
      },
      // 是否开启冻结模式，不可更改所有组件的 rect 信息
      freezeModeChange(freeze) {
        this.updateFreezeMode(freeze);
      },
      // 截图功能 页面元素转图片
      transDomToImage() {
        // 先取消所有组件的选择，避免截图截到组件的 sticks
        this.selectWidgetIds.forEach(sid => {
          const widget = WidgetFactory.getWidgetById(sid);
          widget.active = false;
        });
        this.$nextTick(() => {
          // 选取当前选中的页面的根 widget 进行截图
          const handler = new Dom2ImageHandler();
          handler.transform(this.pageHdl.activePage.id).then(result => {
            const formData = new FormData();
            const fileData = base64toFile(result);
            formData.append("file", fileData, '组件预览图');
            const params = {type: uploadFileType.preview, previewType: 'component'};
            API.file.fileUpload(formData, params).then((resp) => {
              const {files = []} = resp.data;
              const params = {
                type: uploadFileType.preview,
                action: 'add',
                componentId: this.component._id,
                files: files
              };
              API.component.componentFileUpdate(params).then(resp => {
                messageHandle({code: msgCode.UPLOAD_SUCCESS, title: '组件预览图'});
              });
            }).catch((err) => {
              console.log("err: ", err);
            });
          });
        }, 200);
      },
      themeChange(name) {
        let activeTheme;
        const theme = themeOption.find(item => item[name]);
        activeTheme = theme ? theme[name] : [];
        this.updateActiveTheme(activeTheme);
        this.showThemeDialog = false;
      },
      changeTab(type, idx) {
        this.activePickerTab = idx;
        this.widgetType = type;
      },
      jumpLogic(val) {
        this.activeLogic = val.activeLogic;
        this.showIftttDialog = val.showIftttDialog;
      },
      //拿通用协议的命令
      getGlobalCommandList() {
        switch (this.commandType.type) {
          case 'generalProtocol':
            API.generalProtocol.generalProtocolCommandDetail({_id: this.commandType.protocolId}).then((resp) => {
              const {data = []} = resp;
              this.commandData= data;
              this.updateGlobalCommandList(data);
              const deviceList = []
              deviceList.push({
                ...data,
                _id: this.component.devices.length>0?this.component.devices[0]._id: generateUID(),
                deviceCode:'00000000',
                controlId: 'm000000',
                deviceName: data.protocolName,
              })
              this.updateGlobalDeviceList(deviceList);
            }).catch((err) => {
              console.log("err: ", err);
            });
            break;
          case 'deviceProtocol':
            API.protocol.protocolCommandDetail({_id: this.commandType.protocolId}).then((resp) => {
              const {data = []} = resp;
              this.updateGlobalCommandList(data);
              this.commandData= data;
              const deviceList = []
              deviceList.push({
                ...data,
                _id: this.component.devices.length>0?this.component.devices[0]._id: generateUID(),
                deviceCode:'00000000',
                controlId: 'm000000',
                deviceName: data.protocolName,
              })
              this.updateGlobalDeviceList(deviceList);
            }).catch((err) => {
              console.log("err: ", err);
            });
            break;
          default:
            break;
        }
      }
    }
  };
</script>

<style scoped lang="less">
  .color-border {
    width: 28px;
    height: 28px;
    padding: 4px;
    border: 1px solid #e6e6e6;
    border-radius: 4px;

    .color-border-box {
      width: 100%;
      height: 100%;
      background: #f00;
      display: flex;
      align-items: center;
      justify-content: center;

      .arrow {
        color: #fff;
        font-size: 16px;
      }
    }
  }

  .home {
    color: @colorPrimary;
    cursor: pointer;
    margin-right: 8px;
  }

  .editor-container {
    height: 100vh;
    overflow: hidden;

    .editor-header {
      height: 40px;
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding: 0 10px;
      background: #2C2C2C;
      color: @colorWhite;
      z-index: 999;
    }

    .icon-hover:hover {
      color: @colorPrimary;
    }

    .editor-aside {
      width: 300px;
      height: calc(100vh - 40px);
      overflow: auto;
      flex-grow: 0;
      flex-shrink: 0;
      background: #fff;
      border-right: 1px solid #DADCE5;
      box-shadow: 2px 0 5px @colorBlackAlpha05;
      box-sizing: border-box;
      z-index: 999;

      &::-webkit-scrollbar {
        display: none;
      }
    }
  }

  .component-widget-picker-tab {
    display: flex;
    justify-content: flex-start;
    gap: 20px;
    height: 50px;
    line-height: 50px;
    padding-left: 10px;
    border-bottom: 1px #DADCE5 solid;
    border-top: 1px #DADCE5 solid;

    div {
      color: #12131A;
      font-size: 14px;
      font-weight: bold;
      text-align: center;
      cursor: pointer;
    }

    .widget-picker-active-tab {
      color: @colorPrimary;
    }
  }

</style>
